package org.lisen.oauth2example.client.controller;

import lombok.extern.slf4j.Slf4j;
import org.apache.oltu.oauth2.client.OAuthClient;
import org.apache.oltu.oauth2.client.URLConnectionClient;
import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse;
import org.apache.oltu.oauth2.client.response.OAuthResourceResponse;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * 获取授权的控制器
 */
@Controller
@RequestMapping("/client")
@Slf4j
public class GetAuthorizationController {

    private static String CLIENT_ID = "clientId";
    private static String CLIENT_SECRET = "clientSecret";
    private static String CODE_URL = "code";
    private static String ACCESSTOKEN_URL = "http://localhost:8081/authServer/token";
    private static String REDIRECT_URL = "http://localhost:8080/client/callbackCode";
    private static String RESPONSE_TYPE = "code";

    @RequestMapping("/apply-auth-page")
    public String openApplyAuthPage() {
        return "apply-auth";
    }

    /**
     * 客户向资源所有者获取授权码
     *
     * @return
     * @throws OAuthSystemException
     */
    @GetMapping("/getCode")
    public String getCode() throws OAuthSystemException {

        OAuthClientRequest oAuthClientRequest = OAuthClientRequest
                .authorizationLocation(CODE_URL)
                .setClientId(CLIENT_ID)
                .setRedirectURI(REDIRECT_URL)
                .setResponseType(RESPONSE_TYPE)
                .buildQueryMessage();

        String uriString = oAuthClientRequest.getLocationUri();

        //重定向到资源所有者，获取验证码
        return "redirect:http://localhost:8082/rowner/" + uriString;
    }


    /**
     * 1. 资源所有者在生成授权码之后，会回调该接口将授权码传回给客户
     * 2. 客户获取授权码之后，使用该接口向认证服务器申请令牌
     *
     * @param request
     * @return
     */
    @RequestMapping("/callbackCode")
    public String callbackCode(HttpServletRequest request) throws OAuthSystemException, OAuthProblemException {

        String code = request.getParameter("code");
        log.info(" --- 从资源拥有者获取code: " + code + "-----------");

        OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());

        String redirect_url = "http://localhost:8080/client/getResource";

        OAuthClientRequest tokenRequest = OAuthClientRequest
                .tokenLocation(ACCESSTOKEN_URL)
                .setClientId(CLIENT_ID)
                .setClientSecret(CLIENT_SECRET)
                .setGrantType(GrantType.AUTHORIZATION_CODE)
                .setCode(code)
                .setRedirectURI(redirect_url)
                .buildQueryMessage();

        //通过Code，向认证服务器申请令牌
        OAuthJSONAccessTokenResponse tokenResp = oAuthClient.accessToken(tokenRequest, OAuth.HttpMethod.POST);

        //获取令牌
        String accessToken = tokenResp.getAccessToken();
        log.info("客户获取的访问令牌：" + accessToken);

        return"redirect:http://localhost:8080/client/getResource?accessToken="+accessToken;
    }


    /**
     * 使用令牌获取资源服务器中的数据
     *
     * @param accessToken
     * @return
     */
    @GetMapping("/getResource")
    public String getResource(String accessToken,HttpServletRequest request) throws OAuthSystemException, OAuthProblemException {

        log.info("客户使用令牌向资源服务器获取数据 token = " + accessToken);
        OAuthClient oAuthClient =new OAuthClient(new URLConnectionClient());

        String userInfoUrl = "http://localhost:8083/resourceServer/userinfo";

        OAuthClientRequest userInfoRequest =new OAuthBearerClientRequest(userInfoUrl)
                .setAccessToken(accessToken).buildHeaderMessage();

        OAuthResourceResponse resourceResponse =oAuthClient.resource(userInfoRequest, OAuth.HttpMethod.GET, OAuthResourceResponse.class);
        String userInfo = resourceResponse.getBody();

        log.info("客户获取的资源服务器的数据： " + userInfo);
        request.setAttribute("userInfo", userInfo);

        return "showdata";

    }

}
